﻿// Decompiled with JetBrains decompiler
// Type: MCM.Abstractions.SettingsUtils
// Assembly: MCMv5, Version=5.10.2.0, Culture=neutral, PublicKeyToken=null
// MVID: 7AB326B9-B2B4-41C2-9177-68E944071101
// Assembly location: D:\steam\steamapps\workshop\content\261550\2859238197\bin\Win64_Shipping_Client\MCMv5.dll

using BUTR.DependencyInjection;
using BUTR.DependencyInjection.Logger;
using HarmonyLib.BUTR.Extensions;
using MCM.Abstractions.Base;
using MCM.Abstractions.Wrapper;
using MCM.Common;
using System;
using System.Collections.Generic;
using System.Linq;

#nullable enable
namespace MCM.Abstractions
{
  public class SettingsUtils
  {
    public static void CheckIsValid(ISettingsPropertyDefinition prop, object? settings)
    {
      if (settings == null)
        throw new Exception("Settings is null.");
      if (!(prop.PropertyReference is PropertyRef propertyReference))
        return;
      if (!propertyReference.PropertyInfo.CanRead)
        throw new Exception("Property " + propertyReference.PropertyInfo.Name + " in " + settings.GetType().FullName + " must have a getter.");
      if (prop.SettingType != SettingType.Dropdown && !propertyReference.PropertyInfo.CanWrite)
        throw new Exception("Property " + propertyReference.PropertyInfo.Name + " in " + settings.GetType().FullName + " must have a setter.");
      bool flag;
      switch (prop.SettingType)
      {
        case SettingType.Int:
        case SettingType.Float:
          flag = true;
          break;
        default:
          flag = false;
          break;
      }
      if (flag && prop.MinValue == prop.MaxValue)
        throw new Exception("Property " + propertyReference.PropertyInfo.Name + " in " + settings.GetType().FullName + " is a numeric type but the MinValue and MaxValue are the same.");
      if (prop.SettingType != 0 && prop.IsToggle)
        throw new Exception("Property " + propertyReference.PropertyInfo.Name + " in " + settings.GetType().FullName + " is marked as the main toggle for the group but is a numeric type. The main toggle must be a boolean type.");
    }

    public static void ResetSettings(BaseSettings settings)
    {
      BaseSettings instance1;
      int num;
      if (settings is IWrapper wrapper)
      {
        object instance2 = Activator.CreateInstance(wrapper.Object?.GetType());
        if (instance2 != null)
        {
          instance1 = Activator.CreateInstance(wrapper.GetType(), instance2) as BaseSettings;
          num = instance1 != null ? 1 : 0;
          goto label_4;
        }
      }
      num = 0;
label_4:
      if (num != 0)
      {
        SettingsUtils.OverrideSettings(settings, instance1);
      }
      else
      {
        if (!(Activator.CreateInstance(settings.GetType()) is BaseSettings instance3))
          return;
        SettingsUtils.OverrideSettings(settings, instance3);
      }
    }

    public static void OverrideSettings(BaseSettings settings, BaseSettings overrideSettings)
    {
      SettingsUtils.OverrideValues(settings, overrideSettings);
    }

    public static bool Equals(BaseSettings settings1, BaseSettings settings2)
    {
      Dictionary<(string, string), ISettingsPropertyDefinition> dictionary1 = settings1.GetAllSettingPropertyDefinitions().ToDictionary<ISettingsPropertyDefinition, (string, string), ISettingsPropertyDefinition>((Func<ISettingsPropertyDefinition, (string, string)>) (x => (x.DisplayName, x.GroupName)), (Func<ISettingsPropertyDefinition, ISettingsPropertyDefinition>) (x => x));
      Dictionary<(string, string), ISettingsPropertyDefinition> dictionary2 = settings2.GetAllSettingPropertyDefinitions().ToDictionary<ISettingsPropertyDefinition, (string, string), ISettingsPropertyDefinition>((Func<ISettingsPropertyDefinition, (string, string)>) (x => (x.DisplayName, x.GroupName)), (Func<ISettingsPropertyDefinition, ISettingsPropertyDefinition>) (x => x));
      if (dictionary1.Count != dictionary2.Count)
        return false;
      foreach (KeyValuePair<(string, string), ISettingsPropertyDefinition> keyValuePair in dictionary1)
      {
        ISettingsPropertyDefinition newDefinition;
        if (!dictionary2.TryGetValue(keyValuePair.Key, out newDefinition) || !SettingsUtils.Equals(keyValuePair.Value, newDefinition))
          return false;
      }
      return true;
    }

    public static bool Equals(
      ISettingsPropertyDefinition? currentDefinition,
      ISettingsPropertyDefinition? newDefinition)
    {
      if (currentDefinition == null || newDefinition == null)
        return false;
      switch (currentDefinition.SettingType)
      {
        case SettingType.Bool:
        case SettingType.Int:
        case SettingType.Float:
        case SettingType.String:
        case SettingType.Button:
          return currentDefinition.PropertyReference.Value != null && newDefinition.PropertyReference.Value != null && currentDefinition.PropertyReference.Value.Equals(newDefinition.PropertyReference.Value);
        case SettingType.Dropdown:
          return currentDefinition.PropertyReference.Value != null && newDefinition.PropertyReference.Value != null && new SelectedIndexWrapper(currentDefinition.PropertyReference.Value).SelectedIndex.Equals(new SelectedIndexWrapper(newDefinition.PropertyReference.Value).SelectedIndex);
        default:
          return false;
      }
    }

    public static void OverrideValues(BaseSettings current, BaseSettings @new)
    {
      Dictionary<string, SettingsPropertyGroupDefinition> dictionary = current.GetUnsortedSettingPropertyGroups().ToDictionary<SettingsPropertyGroupDefinition, string, SettingsPropertyGroupDefinition>((Func<SettingsPropertyGroupDefinition, string>) (x => x.GroupNameRaw), (Func<SettingsPropertyGroupDefinition, SettingsPropertyGroupDefinition>) (x => x));
      foreach (SettingsPropertyGroupDefinition settingPropertyGroup in @new.GetUnsortedSettingPropertyGroups())
      {
        SettingsPropertyGroupDefinition current1;
        if (dictionary.TryGetValue(settingPropertyGroup.GroupNameRaw, out current1))
        {
          SettingsUtils.OverrideValues(current1, settingPropertyGroup);
        }
        else
        {
          IBUTRLogger<SettingsUtils> service = GenericServiceProvider.GetService<IBUTRLogger<SettingsUtils>>();
          if (service != null)
            service.LogWarning(@new.Id + "::" + settingPropertyGroup.GroupNameRaw + " was not found on, " + current.Id);
        }
      }
    }

    public static void OverrideValues(
      SettingsPropertyGroupDefinition current,
      SettingsPropertyGroupDefinition @new)
    {
      Dictionary<string, SettingsPropertyGroupDefinition> dictionary1 = current.SubGroups.ToDictionary<SettingsPropertyGroupDefinition, string, SettingsPropertyGroupDefinition>((Func<SettingsPropertyGroupDefinition, string>) (x => x.GroupNameRaw), (Func<SettingsPropertyGroupDefinition, SettingsPropertyGroupDefinition>) (x => x));
      Dictionary<string, ISettingsPropertyDefinition> dictionary2 = current.SettingProperties.ToDictionary<ISettingsPropertyDefinition, string, ISettingsPropertyDefinition>((Func<ISettingsPropertyDefinition, string>) (x => x.DisplayName), (Func<ISettingsPropertyDefinition, ISettingsPropertyDefinition>) (x => x));
      foreach (SettingsPropertyGroupDefinition subGroup in @new.SubGroups)
      {
        SettingsPropertyGroupDefinition current1;
        if (dictionary1.TryGetValue(subGroup.GroupNameRaw, out current1))
        {
          SettingsUtils.OverrideValues(current1, subGroup);
        }
        else
        {
          IBUTRLogger<SettingsUtils> service = GenericServiceProvider.GetService<IBUTRLogger<SettingsUtils>>();
          if (service != null)
            service.LogWarning(@new.GroupName + "::" + subGroup.GroupNameRaw + " was not found on, " + current.GroupNameRaw);
        }
      }
      foreach (ISettingsPropertyDefinition settingProperty in @new.SettingProperties)
      {
        ISettingsPropertyDefinition current2;
        if (dictionary2.TryGetValue(settingProperty.DisplayName, out current2))
        {
          SettingsUtils.OverrideValues(current2, settingProperty);
        }
        else
        {
          IBUTRLogger<SettingsUtils> service = GenericServiceProvider.GetService<IBUTRLogger<SettingsUtils>>();
          if (service != null)
            service.LogWarning(@new.GroupNameRaw + "::" + settingProperty.DisplayName + " was not found on, " + current.GroupNameRaw);
        }
      }
    }

    public static void OverrideValues(
      ISettingsPropertyDefinition current,
      ISettingsPropertyDefinition @new)
    {
      if (SettingsUtils.Equals(current, @new))
        return;
      current.PropertyReference.Value = @new.PropertyReference.Value;
    }

    public static bool IsForGenericDropdown(Type type)
    {
      return ((IEnumerable<Type>) type.GetInterfaces()).Any<Type>((Func<Type, bool>) (x => x.IsGenericType && x.GetGenericTypeDefinition() == typeof (IList<>))) & (object) AccessTools2.Property(type, "SelectedIndex", false) != null;
    }

    public static bool IsForTextDropdown(Type type)
    {
      return SettingsUtils.IsForGenericDropdown(type) && type.IsGenericType && (object) AccessTools2.Property(type.GenericTypeArguments[0], "IsSelected", false) == null;
    }

    public static bool IsForCheckboxDropdown(Type type)
    {
      return SettingsUtils.IsForGenericDropdown(type) && type.IsGenericType && (object) AccessTools2.Property(type.GenericTypeArguments[0], "IsSelected", false) != null;
    }

    public static bool IsForTextDropdown(object? obj)
    {
      return obj != null && SettingsUtils.IsForTextDropdown(obj.GetType());
    }

    public static bool IsForCheckboxDropdown(object? obj)
    {
      return obj != null && SettingsUtils.IsForCheckboxDropdown(obj.GetType());
    }

    public static IEnumerable<ISettingsPropertyDefinition> GetAllSettingPropertyDefinitions(
      SettingsPropertyGroupDefinition settingPropertyGroup1)
    {
      foreach (ISettingsPropertyDefinition settingProperty in settingPropertyGroup1.SettingProperties)
        yield return settingProperty;
      foreach (SettingsPropertyGroupDefinition settingPropertyGroup in settingPropertyGroup1.SubGroups)
      {
        foreach (ISettingsPropertyDefinition settingProperty in SettingsUtils.GetAllSettingPropertyDefinitions(settingPropertyGroup))
          yield return settingProperty;
      }
    }

    public static IEnumerable<SettingsPropertyGroupDefinition> GetAllSettingPropertyGroupDefinitions(
      SettingsPropertyGroupDefinition settingPropertyGroup)
    {
      yield return settingPropertyGroup;
      foreach (SettingsPropertyGroupDefinition settingPropertyGroup1 in settingPropertyGroup.SubGroups)
        yield return settingPropertyGroup1;
    }

    public static List<SettingsPropertyGroupDefinition> GetSettingsPropertyGroups(
      char subGroupDelimiter,
      IEnumerable<ISettingsPropertyDefinition> settingsPropertyDefinitions)
    {
      List<SettingsPropertyGroupDefinition> rootCollection = new List<SettingsPropertyGroupDefinition>();
      foreach (ISettingsPropertyDefinition propertyDefinition in settingsPropertyDefinitions)
        SettingsUtils.GetGroupFor(subGroupDelimiter, propertyDefinition, (ICollection<SettingsPropertyGroupDefinition>) rootCollection).Add(propertyDefinition);
      return rootCollection;
    }

    public static SettingsPropertyGroupDefinition GetGroupFor(
      char subGroupDelimiter,
      ISettingsPropertyDefinition sp,
      ICollection<SettingsPropertyGroupDefinition> rootCollection)
    {
      string groupName = sp.GroupName;
      SettingsPropertyGroupDefinition groupFor;
      if (groupName.Contains<char>(subGroupDelimiter))
      {
        string truncatedGroupName;
        string topGroupName = SettingsUtils.GetTopGroupName(subGroupDelimiter, groupName, out truncatedGroupName);
        SettingsPropertyGroupDefinition sgp = rootCollection.GetGroupFromName(topGroupName);
        if (sgp == null)
        {
          sgp = new SettingsPropertyGroupDefinition(topGroupName).SetSubGroupDelimiter(subGroupDelimiter);
          rootCollection.Add(sgp);
        }
        groupFor = SettingsUtils.GetGroupForRecursive(subGroupDelimiter, truncatedGroupName, sgp, sp);
      }
      else
      {
        groupFor = rootCollection.GetGroupFromName(groupName);
        if (groupFor == null)
        {
          groupFor = new SettingsPropertyGroupDefinition(groupName, sp.GroupOrder).SetSubGroupDelimiter(subGroupDelimiter);
          rootCollection.Add(groupFor);
        }
      }
      return groupFor;
    }

    public static SettingsPropertyGroupDefinition GetGroupForRecursive(
      char subGroupDelimiter,
      string groupName,
      SettingsPropertyGroupDefinition sgp,
      ISettingsPropertyDefinition sp)
    {
      while (true)
      {
        if (groupName.Contains<char>(subGroupDelimiter))
        {
          string truncatedGroupName;
          string topGroupName = SettingsUtils.GetTopGroupName(subGroupDelimiter, groupName, out truncatedGroupName);
          SettingsPropertyGroupDefinition settingProp = sgp.GetGroup(topGroupName);
          if (settingProp == null)
          {
            settingProp = new SettingsPropertyGroupDefinition(topGroupName).SetSubGroupDelimiter(subGroupDelimiter);
            sgp.Add(settingProp);
          }
          groupName = truncatedGroupName;
          sgp = settingProp;
        }
        else
          break;
      }
      SettingsPropertyGroupDefinition settingProp1 = sgp.GetGroup(groupName);
      if (settingProp1 == null)
      {
        settingProp1 = new SettingsPropertyGroupDefinition(groupName, sp.GroupOrder).SetSubGroupDelimiter(subGroupDelimiter);
        sgp.Add(settingProp1);
      }
      return settingProp1;
    }

    public static string GetTopGroupName(
      char subGroupDelimiter,
      string groupName,
      out string truncatedGroupName)
    {
      int length = groupName.IndexOf(subGroupDelimiter);
      string topGroupName = groupName.Substring(0, length);
      truncatedGroupName = groupName.Remove(0, length + 1);
      return topGroupName;
    }

    public static IEnumerable<IPropertyDefinitionBase> GetPropertyDefinitionWrappers(object property)
    {
      return SettingsUtils.GetPropertyDefinitionWrappers((IReadOnlyCollection<object>) new object[1]
      {
        property
      });
    }

    public static IEnumerable<IPropertyDefinitionBase> GetPropertyDefinitionWrappers(
      IReadOnlyCollection<object> properties)
    {
      object propAttr = properties.SingleOrDefault<object>((Func<object, bool>) (a => a is IPropertyDefinitionBool));
      if (propAttr != null)
        yield return (IPropertyDefinitionBase) new PropertyDefinitionBoolWrapper(propAttr);
      propAttr = properties.SingleOrDefault<object>((Func<object, bool>) (a => a is IPropertyDefinitionDropdown));
      if (propAttr != null)
        yield return (IPropertyDefinitionBase) new PropertyDefinitionDropdownWrapper(propAttr);
      propAttr = properties.SingleOrDefault<object>((Func<object, bool>) (a => a is IPropertyDefinitionGroupToggle));
      if (propAttr != null)
        yield return (IPropertyDefinitionBase) new PropertyDefinitionGroupToggleWrapper(propAttr);
      propAttr = properties.SingleOrDefault<object>((Func<object, bool>) (a => a is IPropertyDefinitionText));
      if (propAttr != null)
        yield return (IPropertyDefinitionBase) new PropertyDefinitionTextWrapper(propAttr);
      propAttr = properties.SingleOrDefault<object>((Func<object, bool>) (a => a is IPropertyDefinitionWithActionFormat));
      if (propAttr != null)
        yield return (IPropertyDefinitionBase) new PropertyDefinitionWithActionFormatWrapper(propAttr);
      propAttr = properties.SingleOrDefault<object>((Func<object, bool>) (a => a is IPropertyDefinitionWithCustomFormatter));
      if (propAttr != null)
        yield return (IPropertyDefinitionBase) new PropertyDefinitionWithCustomFormatterWrapper(propAttr);
      propAttr = properties.SingleOrDefault<object>((Func<object, bool>) (a => a is IPropertyDefinitionWithEditableMinMax));
      if (propAttr != null)
        yield return (IPropertyDefinitionBase) new PropertyDefinitionWithEditableMinMaxWrapper(propAttr);
      propAttr = properties.SingleOrDefault<object>((Func<object, bool>) (a => a is IPropertyDefinitionWithFormat));
      if (propAttr != null)
        yield return (IPropertyDefinitionBase) new PropertyDefinitionWithFormatWrapper(propAttr);
      propAttr = properties.SingleOrDefault<object>((Func<object, bool>) (a => a is IPropertyDefinitionWithId));
      if (propAttr != null)
        yield return (IPropertyDefinitionBase) new PropertyDefinitionWithIdWrapper(propAttr);
      propAttr = properties.SingleOrDefault<object>((Func<object, bool>) (a => a is IPropertyDefinitionWithMinMax));
      if (propAttr != null)
        yield return (IPropertyDefinitionBase) new PropertyDefinitionWithMinMaxWrapper(propAttr);
      propAttr = properties.SingleOrDefault<object>((Func<object, bool>) (a => a is IPropertyDefinitionButton));
      if (propAttr != null)
        yield return (IPropertyDefinitionBase) new PropertyDefinitionButtonWrapper(propAttr);
      propAttr = properties.SingleOrDefault<object>((Func<object, bool>) (a => a is IPropertyDefinitionGroupMetadata));
      if (propAttr != null)
        yield return (IPropertyDefinitionBase) new PropertyDefinitionGroupMetadataWrapper(propAttr);
    }
  }
}
